#include <scene/SceneNode.h>
#include <base/d3d.h>

SceneNode::SceneNode() {
  _parent = NULL;
  _passes = 1;
}

SceneNode::SceneNode(const SceneNode * rhs) {
  _parent = NULL; 
  _passes = 1;
}

long SceneNode::drawScene(Device * device) {
  long hr = preDraw(device);
  if(hr)
    return hr;

  for(unsigned long pass = 0; pass < _passes; pass++) {
    passDraw(device, pass);
    for(std::vector<SceneNode *>::iterator i = _children.begin(); i != _children.end(); i++) {
      hr = (*i)->drawScene(device);
      if(hr)
        return hr;
    }
  }
  hr = postDraw(device);
  if(hr)
    return hr;
  return 0;
}

void SceneNode::addChild(SceneNode * child) {
  if(child->_parent)
    child->_parent->removeChild(child);

  child->_parent = this;
  _children.push_back(child);
}

void SceneNode::removeChild(SceneNode * child){
  child->_parent = NULL;
  for(std::vector<SceneNode *>::iterator i = _children.begin(); i != _children.end(); i++){
    if(*i == child){
      _children.erase(i);
      return;
    }
  }
}

void SceneNode::removeAll(){
  for(std::vector<SceneNode *>::iterator i = _children.begin(); i != _children.end(); i++) {
    (*i)->_parent = NULL;
  }
  _children.clear();
}

void SceneNode::destroyChildren(){
  for(std::vector<SceneNode *>::iterator i = _children.begin(); i != _children.end(); i++) {
    (*i)->destroyGraph();
  }
  _children.clear();
}

SceneNode * SceneNode::getChild(unsigned long index) const {
  if(index >= _children.size())
    return NULL;
  else
    return _children[index];
}

void SceneNode::destroyGraph() {
  for(std::vector<SceneNode *>::iterator i = _children.begin(); i != _children.end(); i++) {
    (*i)->destroyGraph();
  }
  delete this;
}

SceneNode * SceneNode::copy() const {
  return new SceneNode(this);
}

SceneNode * SceneNode::copyGraph() const {
  SceneNode * newGraph = this->copy();

  for(std::vector<SceneNode *>::const_iterator i = _children.begin(); i != _children.end(); i++) {
    newGraph->addChild((*i)->copyGraph());
  }

  return newGraph;
}

SceneNode * SceneNode::select(const D3DXVECTOR4 & v){
  SceneNode * n = NULL;

  for(std::vector<SceneNode *>::const_reverse_iterator i = _children.rbegin(); i != _children.rend(); i++) {
    n = (*i)->select(v);
    if(n) return n;
  }

  return NULL;
}

TextureNode::TextureNode(){
  color = 0xffffffff;
  texture = NULL;
}

TextureNode::TextureNode(const TextureNode * rhs){
  color = rhs->color;
  texture = rhs->texture;
}

long TextureNode::preDraw(Device * device){
  _prev_color = device->getColor();
  _prev_texture = device->getTexture();
  device->setColor(color);
  device->setTexture(texture);
  return 0;
}

long TextureNode::postDraw(Device * device){
  device->setColor(_prev_color);
  device->setTexture(_prev_texture);
  return 0;
}

SceneNode * TextureNode::copy() const{
  return new TextureNode(color, texture);
}
